import { saveAs } from "file-saver"
import XLSX  from "xlsx/dist/xlsx.full.min"


function datenum(v, date1904) {
    if (date1904) v += 1462
    let epoch = Date.parse(v)
    return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000)
}
 
function data2ws(data) {
    const ws = {}
    const range = {s: {c: 10000000, r: 10000000}, e: {c: 0, r: 0}}
    for (let R = 0; R != data.length; ++R) {
        for (let C = 0; C != data[R].length; ++C) {
            if (range.s.r > R) range.s.r = R
            if (range.s.c > C) range.s.c = C
            if (range.e.r < R) range.e.r = R
            if (range.e.c < C) range.e.c = C
            const cell = { v: data[R][C] }
            if (cell.v == null) continue
            const cell_ref = XLSX.utils.encode_cell({c: C, r: R})
 
            if (typeof cell.v === 'number') cell.t = 'n'
            else if (typeof cell.v === 'boolean') cell.t = 'b'
            else if (cell.v instanceof Date) {
                cell.t = 'n'
                cell.z = XLSX.SSF._table[14]
                cell.v = datenum(cell.v)
            }
            else cell.t = 's'
 
            ws[cell_ref] = cell
        }
    }
    if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range)
    return ws
}

function Workbook() {
    if (!(this instanceof Workbook)) return new Workbook()
    this.SheetNames = []
    this.Sheets = {}
}
 
function s2ab(s) {
    const buf = new ArrayBuffer(s.length)
    const view = new Uint8Array(buf)
    for (let i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF
    return buf
}
 
/*
* th => 表头
* data => 数据
* fileName => 文件名
* fileType => 文件类型
* sheetName => sheet页名
*/
export default function toExcel ({data, fileName}) {

    const excelFoot = ["createTime","patient_foot_id","name","sex","birthDate","age","height","weight","phone","shoeSsize",
    "gaitMeasureMode","balanceMeasureMode","selftalk","protopathy","pain","historyofsurgery","scrutator","doctor","testingTime","loadingRatioLeftMean",
    "loadingRatioRightMean","footflatRatioLeftMean","footflatRatioRightMean","preSwingRatioLeftMean","preSwingRatioRightMean","sdpLeft","sdpRight","swingRatioLeftMean","swingRatioRightMean","mdgpL",
    "mdgpR","adcpqL","adcpqR","admpqL","admpqR","adppqL","adppqR","adspqL","adspqR","stepNumberLeft",
    "stepNumberRight","rundurationtimeLeft","rundurationtimeRight","stepSpeedLeft","stepSpeedRight","stepFrequencyLeft","stepFrequencyRight","stepDistanceLeftMean","stepDistanceRightMean","stepHighLeftMean",
    "stepHighRightMean","stepWidthLeftMean","stepWidthRightMean","loadAngleLeftMean","loadAngleRightMean","preswingAngleLeftMean","preswingAngleRightMean","fpaLeftMean","fpaRightMean","maxFpaLeft",
    "maxFpaRight","minFpaLeft","minFpaRight","maxFpaLeftPhase","maxFpaRightPhase","minFpaLeftPhase","minFpaRightPhase","aleftMean","arightMean","bleftMean",
    "brightMean","cleftMean","crightMean","t1LeftMean","t1RightMean","t2LeftMean","t2RightMean","t3LeftMean","t3RightMean","hvnfCzwarLeft",
    "hvnfCzwarRight","hvwZdwfarLeft","hvwZdwfarRight","hvnfZdwfarLeft","hvnfZdwfarRight","timeVerticalLeftMean","timeVerticalRightMean","timeMaxoutsideangleLeftMean","timeMaxoutsideangleRightMean","c1LeftMean",
    "c1RightMean","t31LeftMean","t31RightMean","hvnfZdnfarLeft","hvnfZdnfarRight","timeMaxinsideangleLeftMean","timeMaxinsideangleRightMean","verticalPhaseLeft","verticalPhaseRight","maxoutsideanglePhaseLeft",
    "maxoutsideanglePhaseRight","maxinsideanglePhaseLeft","maxinsideanglePhaseRight","pressureHeelInsideLoadAddLeft","pressureHeelInsideLoadAddRight","pressureHeelOutsideLoadAddLeft","pressureHeelOutsideLoadAddRight","cpqMlpYlzhrLeft","cpqMlpYlzhrRight","pressureHeelInsideFootflatAddLeft",
    "pressureHeelInsideFootflatAddRight","pressureHeelOutsideFootflatAddLeft","pressureHeelOutsideFootflatAddRight","mpqMlpYlzhrLeft","mpqMlpYlzhrRight","cmpqMlpYlzhrLeft","cmpqMlpYlzhrRight","pressureHeelInsideMaxvalueLeft","pressureHeelInsideMaxvalueRight","pressureHeelOutsideMaxvalueLeft",
    "pressureHeelOutsideMaxvalueRight","timePressureHeelInsideMaxvalueLeft","timePressureHeelInsideMaxvalueRight","timePressureHeelOutsideMaxvalueLeft","timePressureHeelOutsideMaxvalueRight","pressureInsideAddLeft","pressureInsideAddRight","pressureOutsideAddLeft","pressureOutsideAddRight","mlpYlzhrLeft",
    "mlpYlzhrRight","pressureMeanLeft1","pressureMeanRigh1","pressureMeanLeft2","pressureMeanRight2","pressureMeanLeft3","pressureMeanRight3","pressureMeanLeft4","pressureMeanRight4","pressureMeanLeft5",
    "pressureMeanRight5","pressureMeanLeft6","pressureMeanRight6","pressureMeanLeft7","pressureMeanRight7","pressureMeanLeft8","pressureMeanRight8","pressureMeanLeft9","pressureMeanRight9","jdOneToNineApznLeft",
    "jdOneToNineApznRight","jd1AprLeft","jd1AprRight","jd2AprLeft","jd2AprRight","jd3AprLeft","jd3AprRight","jd4AprLeft","jd4AprRight","jd5AprLeft",
    "jd5AprRight","jd6AprLeft","jd6AprRight","jd7AprLeft","jd7AprRight","jd8AprLeft","jd8AprRight","jd9AprLeft","jd9AprRight","jdFourToSixApznLeft",
    "jdFourToSixApznRight","jdFourToSixAprLeft","jdFourToSixAprRight","jdOneTwoEightNineApznLeft","jdOneTwoEightNineApznRight","jdOneTwoEightNineAprLeft","jdOneTwoEightNineAprRight","pressureAddLeft","pressureAddRight","jdYlzhr",
    "timeArchAppearMeanLeft","timeArchAppearMeanRight","timeArchDisappearMeanLeft","timeArchDisappearMeanRight","archMaxvalueLeft","archMaxvalueRight","timeArchMaxvalueLeft","timeArchMaxvalueRight"]
    const excelThree = ["testTime","businessName","address","cityProvince","country","companyPhone","fax","name","dataOfBirth","age","height","weight","bmi","weightBearing","dressShoe","athleticShoe","casualShoe","heels",
    "phone","optionalInputTwo","optionalInputThree","optionalInputFour","optionalInputFive","optionalInputSix","optionalInputSeven","optionalInputEight","optionalInputNine","optionalInputTen",
    "footL","footR","archL","archR","oneHeelTipL","oneHeelTipR","fiveHeelTipL","fiveHeelTipR","hcHeelTipL","hcHeelTipR","latArchHeelTipL","latArchHeelTipR","medArchHeelTipL","medArchHeelTipR","foreFootL","foreFootR","heelL","heelR","midFootL","midFootR","oneToFiveMetL","oneToFiveMetR","heightArchL","heightArchR",
    "angleToeOneL","angleToeOneR","shoeSizeL","shoeSizeR","archMedialHeightL","archMedialHeightR","archAreaHeightL","archAreaHeightR","archLateralHeightL","archLateralHeightR","archIndexL","archIndexR","archIndexTypeL","archIndexTypeR","halluxAngleL","halluxAngleR","halluxAngleTypeL","halluxAngleTypeR",
    "heelAngleL","heelAngleR","legAngleL","legAngleR","medArchAreaL","medArchAreaR","medArchVolumeL","medArchVolumeR","footAreaL","footAreaR","archHeightL","archHeightR","firstMetXCoodinatesL","firstMetYCoodinatesL","firstMetZCoodinatesL","firstMetXCoodinatesR","firstMetYCoodinatesR","firstMetZCoodinatesR",
    "fifthMetXCoodinatesL","fifthMetYCoodinatesL","fifthMetZCoodinatesL","fifthMetXCoodinatesR","fifthMetYCoodinatesR","fifthMetZCoodinatesR","heelCenterXCoodinatesL","heelCenterYCoodinatesL","heelCenterZCoodinatesL","heelCenterXCoodinatesR","heelCenterYCoodinatesR","heelCenterZCoodinatesR",
    "toeTipXCoodinatesL","toeTipYCoodinatesL","toeTipZCoodinatesL","toeTipXCoodinatesR","toeTipYCoodinatesR","toeTipZCoodinatesR","heelTipXCoodinatesL","heelTipYCoodinatesL","heelTipZCoodinatesL","heelTipXCoodinatesR","heelTipYCoodinatesR","heelTipZCoodinatesR","medForeFootXCoodinatesL","medForeFootYCoodinatesL","medForeFootZCoodinatesL",
    "medForeFootXCoodinatesR","medForeFootYCoodinatesR","medForeFootZCoodinatesR","latForeFootXCoodinatesL","latForeFootYCoodinatesL","latForeFootZCoodinatesL","latForeFootXCoodinatesR","latForeFootYCoodinatesR","latForeFootZCoodinatesR","medHeelXCoodinatesL","medHeelYCoodinatesL","medHeelZCoodinatesL","medHeelXCoodinatesR","medHeelYCoodinatesR","medHeelZCoodinatesR",
    "latHeelXCoodinatesL","latHeelYCoodinatesL","latHeelZCoodinatesL","latHeelXCoodinatesR","latHeelYCoodinatesR","latHeelZCoodinatesR","archXCoodinatesL","archYCoodinatesL","archZCoodinatesL","archXCoodinatesR","archYCoodinatesR","archZCoodinatesR","userPointOneXCoodinatesL","userPointOneYCoodinatesL","userPointOneZCoodinatesL","userPointOneXCoodinatesR","userPointOneYCoodinatesR","userPointOneZCoodinatesR",
    "userPointTwoXCoodinatesL","userPointTwoYCoodinatesL","userPointTwoZCoodinatesL","userPointTwoXCoodinatesR","userPointTwoYCoodinatesR","userPointTwoZCoodinatesR","latArchXCoodinatesL","latArchYCoodinatesL","latArchZCoodinatesL","latArchXCoodinatesR","latArchYCoodinatesR","latArchZCoodinatesR","medToeOneXCoodinatesL","medToeOneYCoodinatesL","medToeOneZCoodinatesL","medToeOneXCoodinatesR","medToeOneYCoodinatesR","medToeOneZCoodinatesR"]
    const excelFootHead = ["检测日期","设备id","姓名","性别","出生日期","年龄","身高","体重","联系电话","穿鞋尺码",
    "步态测量模式","平衡测量模式","主诉","是否有原发病（如马蹄足、脑瘫、帕金森等）","疼痛部位","手术史","检查者","申请医生","检测时长","CPQ-L(%)",
    "CPQ-R(%)","MPQ-L(%)","MPQ-R(%)","PPQ-L(%)","PPQ-R(%)","SDP-L(%)","SDP-R(%)","SPMQ-L(%)","SPMQ-R(%)","MDGP-L",
    "MDGP-R","ADCPQ-L","ADCPQ-R","ADMPQ-L","ADMPQ-R","ADPPQ-L","ADPPQ-R","ADSPQ-L","ADSPQ-R","SCS-L",
    "SCS-R","ETJ-L","ETJ-R","APS-L","APS-R","APP-L","APP-R","ASF-L","ASF-R","ASHG-L",
    "ASHG-R","ASWK-L","ASWK-R","CPQ-ATEJ-L","CPQ-ATEJ-R","PPLQ-ATAJ-L","PPLQ-ATAJ-R","AFPA-L","AFPA-R","ZDFPA-L",
    "ZDFPA-R","ZXFPA-L","ZXFPA-R","ZDFPA(cycle)-L","ZDFPA(cycle)-R","ZXFPA(cycle)-L","ZXFPA(cycle)-R","HVNF-CZWJD A-L","HVNF-CZWJD A-R","HVW-ZDWFJD B-L",
    "HVW-ZDWFJD B-R","HVNF-ZDWFJD C-L","HVNF-ZDWFJD C-R","HVNF-CZWSJ T1-L","HVNF-CZWSJ T1-R","HVNF-CZWSJ T2-L","HVNF-CZWSJ T2-R","HVNF-CZWSJ T3-L","HVNF-CZWSJ T3-R","HVNF-CZWAR-L",
    "HVNF-CZWAR-R","HVW-ZDWFAR-L","HVW-ZDWFAR-R","HVNF-ZDWFAR-L","HVNF-ZDWFAR-R","HVW-SK-L","HVW-SK-R","MHVWF-SK-L","MHVWF-SK-R","HVNF-ZDNFJD C'-L",
    "HVNF-ZDNFJD C'-R","HVNF-ZDNFSJ T3'-L","HVNF-ZDNFSJ T3'-R","HVNF-ZDNFAR-L","HVNF-ZDNFAR-R","MHVNF-SK-L","MHVNF-SK-R","HVW(cycle)-L","HVW(cycle)-R","MHVWF(cycle)-L",
    "MHVWF(cycle)-R","MHVNF(cycle)-L","MHVNF(cycle)-R","CPQ-MP-YLZH-L","CPQ-MP-YLZH-R","CPQ-LP-YLZH-L","CPQ-LP-YLZH-R","CPQ-MLP-YLZHR-L","CPQ-MLP-YLZHR-R","MPQ-MP-YLZH-L",
    "MPQ-MP-YLZH-R","MPQ-LP-YLZH-L","MPQ-LP-YLZH-R","MPQ-MLP-YLZHR-L","MPQ-MLP-YLZHR-R","CMPQ-MLP-YLZHR-L","CMPQ-MLP-YLZHR-R","MPC-ZDYLZ-L",
    "MPC-ZDYLZ-R","LPC-ZDYLZ-L","LPC-ZDYLZ-R","MPC-YLCXSJ-L","MPC-YLCXSJ-R","LPC-YLCXSJ-L","LPC-YLCXSJ-R","MPL-YLZH-L","MPL-YLZH-R","LPL-YLZH-L",
    "LPL-YLZH-R","MLP-YLZHR-L","MLP-YLZHR-R","JD1-APVZ-L","JD1-APVZ-R","JD2-APVZ-L","JD2-APVZ-R","JD3-APVZ-L","JD3-APVZ-R","JD4-APVZ-L",
    "JD4-APVZ-R","JD5-APVZ-L","JD5-APVZ-R","JD6-APVZ-L","JD6-APVZ-R","JD7-APVZ-L","JD7-APVZ-R","JD8-APVZ-L","JD8-APVZ-R","JD9-APVZ-L",
    "JD9-APVZ-R","JD123456789-APZH-L","JD123456789-APZH-R","JD1-APR-L","JD1-APR-R","JD2-APR-L","JD2-APR-R","JD3-APR-L","JD3-APR-R","JD4-APR-L",
    "JD4-APR-R","JD5-APR-L","JD5-APR-R","JD6-APR-L","JD6-APR-R","JD7-APR-L","JD7-APR-R","JD8-APR-L","JD8-APR-R","JD9-APR-L",
    "JD9-APR-R","JD456-APZH-L","JD456-APZH-R","JD456-APR-L","JD456-APR-R","JD1289-APZH-L","JD1289-APZH-R","JD1289-APR-L","JD1289-APR-R","JDYLZH-L",
    "JDYLZH-R","JDYLZHR","APL-CXSJ-L","APL-CXSJ-R","APL-XSSJ-L","APL-XSSJ-R","APL-ZDZ-L","APL-ZDZ-R","APL-ZDZSK-L","APL-ZDZSK-R"]

    const excelThreeHead = ["检测时间","Business Name","Address","City, Province","Country","Phone","Fax","Name","Date of Birth","Age","Height(cm)","Weight(kg)","BMI","Weight Bearing %","Dress Shoe","Athletic Shoe","Casual Shoe","Heels",
    "联系电话","Optional Input 2","Optional Input 3","Optional Input 4","Optional Input 5","Optional Input 6","Optional Input 7","Optional Input 8","Optional Input 9","Optional Input 10",
    "Foot Length -L","Foot Length -R","Arch Length -L","Arch Length -R","1 Met to Heel Tip Length -L","1 Met to Heel Tip Length -R","5 Met to Heel Tip Length-L","5 Met to Heel Tip Length-R",
    "HC to Heel Tip Length-L","HC to Heel Tip Length-R","Lat Arch to Heel Tip Length-L","Lat Arch to Heel Tip Length-R","Med Arch to Heel Tip Length-L","Med Arch to Heel Tip Length-R",
    "ForeFoot Width-L","ForeFoot Width-R","Heel Width-L","Heel Width-R","Mid-Foot Width-L","Mid-Foot Width-R","1-5 Met Width-L","1-5 Met Width-R","Arch Heigh-L","Arch Heigh-R","Toe 1 Angle-L","Toe 1 Angle-R",
    "Shoe>Foot 15mm(Shoe Size By Foot Length)-L","Shoe>Foot 15mm(Shoe Size By Foot Length)-R",
    "Arch Medial Height-L","Arch Medial Height-R","Arch Area Height-L","Arch Area Height-R","Arch Lateral Height-L","Arch Lateral Height-R","Arch Index-L","Arch Index-R","Arch Type-L","Arch Type-R",
    "Hallux Angle-L","Hallux Angle-R","Hallux Angle Type-L","Hallux Angle Type-R","Heel Angle-L","Heel Angle-R","Leg Angle-L","Leg Angle-R","Med Arch Area-L","Med Arch Area-R","Med Arch Volume-L","Med Arch Volume-R",
    "Foot Projection Area without Toes-L","Foot Projection Area without Toes-R","Arch Area Relative Height-L","Arch Area Relative Height-R",
    "1st Met -X-L","1st Met -Y-L","1st Met -Z-L","1st Met -X-R","1st Met -Y-R","1st Met -Z-R","5th Met-X-L","5th Met-Y-L","5th Met-Z-L","5th Met-X-R","5th Met-Y-R","5th Met-Z-R",
    "Heel Center -X-L","Heel Center -Y-L","Heel Center -Z-L","Heel Center -X-R","Heel Center -Y-R","Heel Center -Z-R","Toe Tip -X-L","Toe Tip -Y-L","Toe Tip -Z-L","Toe Tip -X-R","Toe Tip -Y-R","Toe Tip -Z-R","Heel Tip-X-L","Heel Tip-Y-L","Heel Tip-Z-L","Heel Tip-X-R","Heel Tip-Y-R","Heel Tip-Z-R","Med ForeFoot-X-L","Med ForeFoot-Y-L","Med ForeFoot-Z-L","Med ForeFoot-X-R","Med ForeFoot-Y-R","Med ForeFoot-Z-R","Lat ForeFoot -X-L","Lat ForeFoot -Y-L","Lat ForeFoot -Z-L","Lat ForeFoot -X-R","Lat ForeFoot -Y-R","Lat ForeFoot -Z-R","Med Heel -X-L","Med Heel -Y-L","Med Heel -Z-L","Med Heel -X-R","Med Heel -Y-R","Med Heel -Z-R","Lat Heel-X-L","Lat Heel-Y-L","Lat Heel-Z-L","Lat Heel-X-R","Lat Heel-Y-R","Lat Heel-Z-R","Arch -X-L","Arch -Y-L","Arch -Z-L","Arch -X-R","Arch -Y-R","Arch -Z-R","User Point 1 -X-L","User Point 1 -Y-L","User Point 1 -Z-L","User Point 1 -X-R","User Point 1 -Y-R","User Point 1 -Z-R","User Point 2 -X-L","User Point 2 -Y-L","User Point 2 -Z-L","User Point 2 -X-R","User Point 2 -Y-R","User Point 2 -Z-R","Lat Arch -X-L","Lat Arch -Y-L","Lat Arch -Z-L","Lat Arch -X-R","Lat Arch -Y-R","Lat Arch -Z-R","Med Toe 1 -X-L","Med Toe 1 -Y-L","Med Toe 1 -Z-L","Med Toe 1 -X-R","Med Toe 1 -Y-R","Med Toe 1 -Z-R"
]
    let sheetName = ["步态传感器","3D扫描"];  //sheet名
    const filterVal = [excelFoot,excelThree];  //列名    原始数据字段key
    const filterVal1 = [excelFootHead,excelThreeHead];  //列名   excel表头需与filterVal字段顺序一致
    var keys=["sheet1","sheet2"]; //json数据键名
    var len = Object.keys(data).length;  //json数据长度   data中的属性名长度
    const wb = new Workbook();
    for(var i=0; i < len; i++){
        var data1temp = data[keys[i]];
        if(data1temp==null){
            continue;
        }else{
            var data1 = data1temp.map(v => filterVal[i].map(k => v[k]));
                /*
            data[keys[i]]----data中的sheet1 、sheet2
            v----sheet1=原始数据数组[]
            filterVal[i]----excelFoot[]
            k----excelFoot[]数组中的字段
            v[k]----原始数据对应的excelFoot[]数组中的字段------>filterVal[字段值]
            data1----[[第一个人数据][第二个人数据][第三个人数据]]
            */
            data1.unshift(filterVal1[i]);
            //data1----[[表头][第一个人数据][第二个人数据][第三个人数据]]
            var ws = data2ws(data1);
                 /*设置worksheet每列的最大宽度*/
                 const colWidth = data1.map(row => row.map(val => {
                    /*先判断是否为null/undefined*/
                    if (val == null) return {'wch': 10};
                    /*再判断是否为中文*/
                    else if (val.toString().charCodeAt(0) > 255) return {'wch': val.toString().length * 2};
                    else return {'wch': val.toString().length};
                }))
                /*以第一行为初始值*/
            let result = colWidth[0];
            for (let i = 1; i < colWidth.length; i++) {
                for (let j = 0; j < colWidth[i].length; j++) {
                if (result[j]['wch'] < colWidth[i][j]['wch']) {
                    result[j]['wch'] = colWidth[i][j]['wch'];
                }
                }
            }
            ws['!cols'] = result;
            var sheetName1 = sheetName[i];   //sheetName1:第i个sheet的名
            wb.SheetNames.push(sheetName1)
            wb.Sheets[sheetName1] = ws
        }
    }
    const fileType = 'xlsx'
    var wbout = XLSX.write(wb, {bookType: fileType, bookSST: false, type: 'binary'})
    fileName = fileName || '列表'
    saveAs(new Blob([s2ab(wbout)], {type: "application/octet-stream"}), `${fileName}.${fileType}`)
  }
